package top.hymsk.ecommerce.aop;

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;


/**
 * 切面类
 * 进行缓存操作，将数据库频繁需要查询使用的数据进行缓存在Redis中，缓存时间为15~45分钟(防止缓存雪崩)
 *
 * @author 花于陌上开
 */
@Component
@Aspect
public class RedisCacheAspect {

    private final StringRedisTemplate stringRedisTemplate;

    public RedisCacheAspect(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Around("@annotation(top.hymsk.ecommerce.anno.RedisCache)")
    public Object redisCache(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取请求方法
//        String methodName = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        String methodName = joinPoint.getSignature().getName();  //在mapper层，不书写重复函数名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String key = "cache:" + methodName + ":" + Arrays.toString(joinPoint.getArgs());
        String resultString = stringRedisTemplate.opsForValue().get(key);
        if (resultString != null) {
            return JSON.parseObject(resultString, methodSignature.getReturnType());
        }
        //执行原目标方法
        Object result = joinPoint.proceed();
        resultString = JSON.toJSONString(result);
        stringRedisTemplate.opsForValue().set(key, resultString, (long) (60 * 15 + Math.random() * 60 * 30), TimeUnit.SECONDS);
        return result;
    }
}
